package com.xinz.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xinz.Constants;
import com.xinz.cache.PlayerCache;
import com.xinz.config.ConfigHelper;
import com.xinz.config.model.ConfigRoom;
import com.xinz.dao.PlayerAchievementDao;
import com.xinz.dao.PlayerDao;
import com.xinz.model.Player;
import com.xinz.model.PlayerAchievement;
import com.xinz.srmi.Session;
import com.xinz.server.ClientPool;
import com.xinz.server.MatchServer;
import com.xinz.shared.exception.GameException;
import com.xinz.shared.exception.NotEnoughGoldException;
import com.xinz.shared.player.ClientPlayerInterface;
import com.xinz.shared.player.PlayerInterface;
import com.xinz.shared.player.SharePlayer;
import com.xinz.util.DateUtil;

public class PlayerService {

	private static final Logger log = LoggerFactory.getLogger(PlayerService.class);
	private static PlayerDao playerDao = new PlayerDao();
	private static PlayerAchievementDao playerAchievementDao = new PlayerAchievementDao();
	
	/**
	 * 生成SharePlayer信息
	 * @param player
	 * @return
	 */
	public static SharePlayer makeSharePlayer(final Player player) {
		SharePlayer sharePlayer = new SharePlayer();
		
		sharePlayer.setBoy(player.isBoy());
		sharePlayer.setDrawTimes(player.getDrawTimes());
		sharePlayer.setFleeTimes(player.getFleeTimes());
		sharePlayer.setGold(player.getGold());
		sharePlayer.setHeadIcon(player.getHeadIcon());
		sharePlayer.setId(player.getId());
		sharePlayer.setLoseTimes(player.getLoseTimes());
		sharePlayer.setMoney(player.getMoney());
		sharePlayer.setName(player.getName());
		sharePlayer.setScore(player.getScore());
		sharePlayer.setStatus(player.getStatus());
		sharePlayer.setWinTimes(player.getWinTimes());
		
		return sharePlayer;
	}
	
	/**
	 * 登陆
	 * @param pid
	 * @param name
	 * @return
	 */
	public static Player login(String pid, String name) {
		if(name == null || pid == null || "".equals(name) || "".equals(pid)) {
			throw new GameException("用户名和密码不能为空");
		}
		Player player = PlayerCache.instance.getPlayer(pid);
		// 用户名判断
		if(player == null) {
			// 用户名不存在则创建账号
			player = createPlayer(pid, name);
		}
		// 账号是否禁止
		int now = DateUtil.now();
		// 到达解禁时间
		if(now >= player.getBanAccountTime()) {
			player.setBanAccountTime(0);
		}
		if(player.getBanAccountTime() > 0) {
			throw new GameException("您的账号已被禁");
		}
		
		// 登录时间判断
		resetData(player);
		player.setLastLoginTime(player.getLoginTime());
		player.setLoginTime(now);
		player.setAccessTime(now);
		player.setStatus(PlayerInterface.STATUS_ONLINE);
		// 更新DB
		playerDao.save(player);
		// 添加Cache
		PlayerCache.instance.addCache(player);
		
		// Session持久化
		Session session = Session.getCurrent();
		session.setTag(Constants.SESSION_ID, player.getId());
		
		// 流程日志数据
		session.setTag(Constants.FLOW_GOLD, player.getGold());
		session.setTag(Constants.FLOW_MONEY, player.getMoney());
		session.setTag(Constants.FLOW_SCORE, player.getScore());
		session.setTag(Constants.FLOW_START_TIME, System.currentTimeMillis());
		ClientPool.addClient(player.getId(), session);
		return player;
	}
	
	/**
	 * 创建Player
	 * @param pid
	 * @param name
	 * @return
	 */
	public static Player createPlayer(String pid, String name) {
		// 创建玩家信息
		Player newPlayer = new Player();
		newPlayer.setId(pid);
		newPlayer.setName(name);
		newPlayer.setMoney(1000);
		int now = DateUtil.now();
		newPlayer.setAccessTime(now);
		newPlayer.setCreateTime(now);
		playerDao.save(newPlayer);
		
		// 创建玩家成就
		PlayerAchievement playerAchievement = new PlayerAchievement();
		playerAchievement.setId(pid);
		playerAchievementDao.save(playerAchievement);
		
		return newPlayer;
	}
	
	/**
	 * 隔天更新数据
	 * @param player
	 */
	public static void resetData(Player player) {
		// 访问时间隔天需要重置任务
		Calendar calendar = Calendar.getInstance();
		int today = calendar.get(Calendar.DAY_OF_YEAR);
		calendar.setTime(new Date(player.getAccessTime() * 1000l));
		// 时间过期则重置每日业务
		if (today != calendar.get(Calendar.DAY_OF_YEAR)) {
			// 重置每日任务
		}
		player.setAccessTime((int)(System.currentTimeMillis() / 1000));
	}
	
	/**
	 * 消耗RMB
	 * @param player
	 * @param gold
	 * @throws GameException
	 */
	public static void consumeGold(Player player, int gold) throws GameException {
		if(player.getGold() < gold) {
			throw new NotEnoughGoldException("你身上的金币不足");
		}
		player.setGold(player.getGold() - gold);
		playerDao.save(player);
	}
	
	/**
	 * 进入房间
	 * @param room
	 * @param self
	 * @return
	 * @throws GameException
	 */
	public static SharePlayer entry(int room, Player self) throws GameException{
		log.error("entryRoom:" + room + ",self" + self.getName());
		// 进入条件判断
		ConfigRoom configRoom = ConfigHelper.getConfigRoom(room);
		if(self.getMoney() < configRoom.getEntryMoney()) {
			throw new GameException("你的金币不足，请到商城购买");
		}
		if(configRoom.getUnEntryMoney() != 0 && self.getMoney() > configRoom.getUnEntryMoney()) {
			String name = configRoom.getName();
			for(int i = room + 1; i <= 4; ++i) {
				ConfigRoom tempRoom = ConfigHelper.getConfigRoom(i);
				if(tempRoom.getUnEntryMoney() != 0 && self.getMoney() > configRoom.getUnEntryMoney()) {
					continue;
				}
				name = tempRoom.getName();
			}
			throw new GameException("低级场已经不能提现你的水平了，请到" + name);
		}
		
		// 进入
		MatchServer.instance.entryRoom(self, room);
		
		Session selfClient = ClientPool.getSelfSession(self.getId());
		
		// 检查是否匹配上
		String targetId = self.getTargetPid();
		// 更新玩家数据
		if( targetId != null ){
			Player target = PlayerCache.instance.getPlayer(targetId);
			// 执行配对,通知对方
			Session targetClient = ClientPool.getTargetSession(targetId);
			if(target != null && self.getId().equals(target.getTargetPid()) && targetClient != null){
				// 自己匹配了玩家			
				selfClient.getImpl(ClientPlayerInterface.class).onMatch(makeSharePlayer(target));
				targetClient.getImpl(ClientPlayerInterface.class).onMatch(makeSharePlayer(self));
				
				if (target.getBattleStatus() >= 2 && self.getBattleStatus()!= Constants.BATTLE_STATUS_GAMING ) {
					selfClient.getImpl(ClientPlayerInterface.class).onReady(makeSharePlayer(target));
				}
			}
			else{
				self.setTargetPid(null);
			}
		}
		return makeSharePlayer(self);
	}
	
	/**
	 * 换桌
	 * @param self
	 * @throws GameException
	 */
	public static void switchTable(Player self) throws GameException{
		
		// 通知客户端
		String targetId = self.getTargetPid();
		
		// 解除自己和对方的关系
		if(self.getTargetPid() == null){
			self.setBattleStatus(Constants.BATTLE_STATUS_UNENTRY);
		}
		else{
			Player target = PlayerCache.instance.getPlayer(self.getTargetPid());
			if( target != null ){
				target.setTargetPid(null);
				target.setMatchTime(0);
			}
			self.setTargetPid(null);
			self.setMatchTime(0);
		}
		
		// 通知客户端
		Session selfClient = ClientPool.getSelfSession(self.getId());
		selfClient.getImpl(ClientPlayerInterface.class).switchTable(makeSharePlayer(self));

		if( targetId != null ){
			log.error("sb1:"+targetId);
			Session targetClient = ClientPool.getTargetSession(targetId);		
			if(targetClient == null){
				self.setTargetPid(null);
				log.error("bug, 配对玩家"+targetId+"已离线?");
			}
			else{
				log.error("sb1:" + targetId);
				targetClient.getImpl(ClientPlayerInterface.class).switchTable(makeSharePlayer(self));
			}
		}
		
		// 重新进入
		// entry(self.getRoom(), self);
	}
	
	/**
	 * 退出，返回大厅
	 * @param self
	 */
	public static void quit(Player self)  throws GameException{
		
		// 通知客户端
		String targetId = self.getTargetPid();
		
		// 退出
		if(self.getTargetPid() == null){
			self.setBattleStatus(Constants.BATTLE_STATUS_UNENTRY);
		}
		else{
			Player target = PlayerCache.instance.getPlayer(self.getTargetPid());
			if( target != null ){
				target.setTargetPid(null);
				target.setMatchTime(0);
			}
			self.setTargetPid(null);
			self.setMatchTime(0);
		}
		
		// 从匹配队列中清除
		MatchServer.instance.clearScoreMap(self);
		self.setRoom(0);
		
		if( targetId != null ){
			Player target = PlayerCache.instance.getPlayer(targetId);
			if( target!=null){
				Session targetClient = ClientPool.getSelfSession(targetId);
				if(targetClient!=null){
					targetClient.getImpl(ClientPlayerInterface.class).quit(makeSharePlayer(target));
				}
			}
		}
	}
	
	/**
	 * 退出游戏
	 * @param self
	 */
	public static void exit(Player self)  throws GameException{
		// 逃跑
		self.setFleeTimes(self.getFleeTimes() + 1);
		playerDao.save(self);
		
		log.info("exit:" + self.getId());
		// 确认页面
		if(self.getBattleStatus() == Constants.BATTLE_STATUS_CONFIRM || self.getBattleStatus() ==  Constants.BATTLE_STATUS_START){
			log.info("exit quit:" + self.getId());
			quit(self);
		}
		// 在游戏中则先停止游戏
		if(self.getBattleStatus() >= Constants.BATTLE_STATUS_GAMING){
			log.info("exit lose:" + self.getId());
			SpotService.lose(self);
		}
		// 清理内存
		PlayerCache.instance.removePlayerFromCache(self.getId());
		ClientPool.removeSession(self.getId());
	}
	
	
	/**
	 * 准备
	 */
	public static void ready(Player self)  throws GameException{
		try{
			// 进入
			MatchServer.instance.ready(self);
			
			Session selfClient = ClientPool.getSelfSession(self.getId());
			
			// 检查是否匹配上
			String targetId = self.getTargetPid();
			// 更新玩家数据
			selfClient.getImpl(ClientPlayerInterface.class).onReady(makeSharePlayer(self));
			if(targetId != null){
				Player target = PlayerCache.instance.getPlayer(targetId);
				if(target != null && self.getId().equals(target.getTargetPid())){
					// 通知对方，自己已经ready
					Session targetClient = ClientPool.getSelfSession(targetId);
					targetClient.getImpl(ClientPlayerInterface.class).onReady(makeSharePlayer(self));
					
					if(self.getBattleStatus() >= Constants.BATTLE_STATUS_START && target.getBattleStatus() >= Constants.BATTLE_STATUS_START){
						//startChess(self);
						//startChess(target);
					}
				}
			}
		}
		catch(Exception e){
			log.error("准备异常:",e);
		}
	}
	
	/**
	 * 开始找茬
	 * @param self
	 */
	public static void startSpot(Player self)  throws GameException{
//		String targetId = self.getTargetPid();
//		Player target = PlayerCache.instance.getPlayer(targetId);
//		if(!(self.getId().equals(target.getTargetPid()) && targetId.equals(target.getId()))){
//			throw new GameException("对方已离开，开始游戏失败！");
//		}
//		
//		// 如果双方都已经ready则进行先手
//		List<ShareChessman> shareChessmanList = new ArrayList<ShareChessman>();
//		Spot chess = ChessService.getChess(self);
//		if(chess != null){
//			Chessman[][] chessArray = chess.getChessArray();
//			for(int i = 0; i < chessArray.length; ++i){
//				for(int j = 0; j < chessArray[i].length; ++j){
//					Chessman chessman = chessArray[i][j];
//					ShareChessman shareChessman = new ShareChessman();
//					if(chessman != null){
//						shareChessman.setCamp(chessman.getCamp());
//						// 需要隐藏
//						if(chessman.isVisable()){
//							shareChessman.setNumber(chessman.getNumber());
//						}
//						shareChessman.setVisable(chessman.isVisable());
//					}
//					else{
//						shareChessman.setCamp(-1);
//						// 未知棋子（number==0）
//						shareChessman.setVisable(true);
//						shareChessman.setNumber(0);
//					}
//					shareChessman.setI(i);
//					shareChessman.setJ(j);
//					shareChessmanList.add(shareChessman);
//				}
//			}
//			log.info("call client start chess:" + chess.getKey());
//		}
//		Session selfClient = ClientPool.getSelfSession(self.getId());		
//		selfClient.getImpl(ClientSpotInterface.class).startChess(makeSharePlayer(self), shareChessmanList);
	}
	
	/**
	 * 加钱
	 * @param self
	 * @param money
	 */
	public static void addMoney(Player self, int money){
		self.setMoney(self.getMoney() + money);
		playerDao.save(self);
	}
	
	/**
	 * 积分 
	 */
	public static void changeIntegral(Player self, int score){
		self.setScore(self.getScore() + score);
		playerDao.save(self);
	}
	
	/**
	 * 加减钱
	 * @param self
	 * @param money
	 */
	public static void changeMoney(Player self, int money){
		self.setMoney(self.getMoney() + money);
		playerDao.save(self);
	}
	
	/**
	 * 加减钱
	 * @param self
	 * @param money
	 */
	public static void changeGold(Player self, int gold){
		self.setGold(self.getGold() + gold);
		if(gold > 0){
			self.setTotalGold(self.getTotalGold() + gold);
		}
		playerDao.save(self);
	}
	
	/**
	 * 在线数据
	 * @return
	 */
	public static Map<Integer, Integer> onlineNumMap(){
		Map<String, Player> playerCache = PlayerCache.instance.getPlayerCache();
		Map<Integer, Integer> onlineNumMap = new HashMap<Integer,Integer>();
		for (Map.Entry<String, Player> onlineEntry : playerCache.entrySet()) {
			String uid = onlineEntry.getKey();
			Player player = onlineEntry.getValue();
			if(player.getRoom() > 0){
				Integer num = onlineNumMap.get(player.getRoom());
				if(num == null){
					onlineNumMap.put(player.getRoom(), 1);
				}
				else{
					onlineNumMap.put(player.getRoom(), num+1);
				}
			}
		}
		return onlineNumMap;
	}
}
